package org.csu.user.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import org.csu.user.entity.dto.UserDTO;
import org.csu.user.entity.po.Users;
import org.csu.user.mapper.UsersMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.csu.user.service.IUsersService;
import org.csu.user.utils.EncryptUtils;
import org.csu.utils.TokenTools;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author
 * @since 2025-07-08
 */
@Service
@RequiredArgsConstructor
public class UsersServiceImpl extends ServiceImpl<UsersMapper, Users> implements IUsersService {
    private final UsersMapper usersMapper;
    private final JavaMailSender mailSender;
    private final TokenTools tokenTools;
    private final RedisTemplate<String, Object> redisTemplate;

    @Override
    public Map<String, Object> login(UserDTO userDTO) {
        List<Users> userList = usersMapper.login(userDTO);
        for (Users users : userList) {
            if (EncryptUtils.matches(userDTO.getPassword(), users.getPassword())) {
                return _getLoginSuccessInfo(users);
            }
        }
        return null;
    }

    @Override
    public Users register(Users user) {
        LambdaQueryWrapper<Users> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(user.getEmail() != null && !user.getEmail().isEmpty(), Users::getEmail, user.getEmail());
        wrapper.eq(user.getPhone() != null && !user.getPhone().isEmpty(), Users::getPhone, user.getPhone());
        Users one = getOne(wrapper);
        if (one != null) {
            throw new RuntimeException("该邮箱或手机号已被注册");
        }
        user.setUid(_generateId());
        user.setIdentity(_generateIdentity("2025", 10));
        user.setPassword(EncryptUtils.encode(user.getPassword()));
        save(user);
        return user;
    }

    @Override
    public void sendEmailCode(String email) {
        LambdaQueryWrapper<Users> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(email != null && !email.isEmpty(), Users::getEmail, email);
        if (getOne(wrapper) == null) {
            throw new RuntimeException("未注册的邮箱");
        }
        String code = String.valueOf(_generateId()).substring(0, 6);
        sendVerificationEmail(email, code);
        redisTemplate.opsForValue().set("verify::" + email, code, 3, TimeUnit.MINUTES);
    }

    @Override
    public Map<String, Object> loginByEmail(Map<String, Object> userDTO) {
        String email = (String) userDTO.get("email");
        if (email == null || email.isEmpty()) {
            throw new RuntimeException("邮箱不能为空");
        }
        String code = (String) redisTemplate.opsForValue().get("verify::" + email);
        if (code == null) {
            throw new RuntimeException("验证码已过期");
        }
        if (!code.equals(userDTO.get("code"))) {
            throw new RuntimeException("验证码错误");
        }
        LambdaQueryWrapper<Users> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Users::getEmail, email);
        Users one = getOne(wrapper);
        if (one == null) {
            throw new RuntimeException("未注册的邮箱");
        }
        return _getLoginSuccessInfo(one);
    }

    @Override
    public String refreshToken(String refreshToken) {
        if (refreshToken == null || refreshToken.isEmpty()) {
            throw new RuntimeException("refreshToken不能为空");
        }
        Long uid = (Long) redisTemplate.opsForValue().get("verify::" + refreshToken);
        if (uid == null) {
            throw new RuntimeException("refreshToken已过期");
        }
        String token = (String) redisTemplate.opsForValue().get("verify::" + uid);
        if (token == null || !token.equals(refreshToken)) {
            redisTemplate.delete("verify::" + refreshToken);
            throw new RuntimeException("refreshToken错误");
        }
        //return tokenTools.createShortToken(uid);
        return "";
    }

    @Override
    public void logout(long userId) {
        redisTemplate.delete("verify::" + userId);
    }

    @Override
    public Users changeProfile(Users user) {
        updateById(user);
        return user;
    }

    @Override
    public void changePassword(Map<String, Object> dto, long userId) {
        Users user = getById(userId);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }
        if (!EncryptUtils.matches((String) dto.get("oldPassword"), user.getPassword())) {
            throw new RuntimeException("原密码错误");
        }
        user.setPassword(EncryptUtils.encode((String) dto.get("newPassword")));
        updateById(user);
    }

    @Override
    public void changeAvatar(MultipartFile file, long userId) {
        // 暂不实现
    }


    private Map<String, Object> _getLoginSuccessInfo(Users one) {
        Map<String, Object> res = new HashMap<>();
        String refreshToken = tokenTools.createLongToken(String.valueOf(one.getUid()));
        res.put("user", one);
        res.put("token", /*tokenTools.createShortToken(one.getUid())*/"");
        res.put("refreshToken", refreshToken);
        redisTemplate.opsForValue().set("verify::" + refreshToken, one.getUid(), 7, TimeUnit.DAYS);
        redisTemplate.opsForValue().set("verify::" + one.getUid(), refreshToken, 7, TimeUnit.DAYS);
        return res;
    }

    /**
     * 生成唯一ID
     *
     * @return 生成的ID
     */
    private long _generateId() {
        return System.currentTimeMillis() + ThreadLocalRandom.current().nextInt(1000);
    }

    private String _generateIdentity(String prefix, int length) {
        // 生成UUID并移除"-"
        String uuid = UUID.randomUUID().toString().replace("-", "");

        // 转换为数字（取前几位）
        StringBuilder numericId = new StringBuilder();
        for (char c : uuid.toCharArray()) {
            if (Character.isDigit(c)) {
                numericId.append(c);
            } else {
                // 字母转换为数字 (A=10, B=11, ...)
                numericId.append((int) c - 55);
            }
            // 达到指定长度则停止
            if (numericId.length() >= length - prefix.length()) {
                break;
            }
        }

        // 组合前缀和数字部分
        return prefix + numericId;
    }

    private void sendVerificationEmail(String to, String code) {
        SimpleMailMessage message = new SimpleMailMessage();
        message.setTo(to);
        message.setSubject("邮箱验证 - 登录确认");
        message.setText("您的验证码是：" + code + "\n有效期为5分钟。");
        mailSender.send(message);
    }
}
